+2005-10-11 Matthias Clasen <mclasen@redhat.com>
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off
+ toggle here with the matching on toggle if it immediately follows.
+ This is a common case, and handling it here prevents quadratic blowup
+ in cleanup_line() below. (#317125)
+
+ * gtk/gtktextsegment.h:
+ * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass
+ the character counts into this function instead of computing them
+ again.
+
2005-10-10 Tommi Komulainen <tommi.komulainen@iki.fi>
* gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
+2005-10-11 Matthias Clasen <mclasen@redhat.com>
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off
+ toggle here with the matching on toggle if it immediately follows.
+ This is a common case, and handling it here prevents quadratic blowup
+ in cleanup_line() below. (#317125)
+
+ * gtk/gtktextsegment.h:
+ * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass
+ the character counts into this function instead of computing them
+ again.
+
2005-10-10 Tommi Komulainen <tommi.komulainen@iki.fi>
* gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
/*
- * gtktextbtree.c --
+ * Gtktextbtree.c --
*
* This file contains code that manages the B-tree representation
* of text for the text buffer and implements character and
* of the deletion range. */
GtkTextLineSegment *last_seg; /* The segment just after the end
* of the deletion range. */
- GtkTextLineSegment *seg, *next;
+ GtkTextLineSegment *seg, *next, *next2;
GtkTextLine *curline;
GtkTextBTreeNode *curnode, *node;
GtkTextBTree *tree;
seg->next = start_line->segments;
start_line->segments = seg;
}
- else
- {
+ else if (prev_seg->next &&
+ seg->type == >k_text_toggle_off_type &&
+ prev_seg->next->type == >k_text_toggle_on_type &&
+ seg->body.toggle.info == prev_seg->next->body.toggle.info)
+ {
+ /* Try to match an off toggle with the matching on toggle
+ * if it immediately follows. This is a common case, and
+ * handling it here prevents quadratic blowup in
+ * cleanup_line() below. See bug 317125.
+ */
+ next2 = prev_seg->next->next;
+ g_free ((char *)prev_seg->next);
+ prev_seg->next = next2;
+ g_free ((char *)seg);
+ seg = NULL;
+ }
+ else
+ {
seg->next = prev_seg->next;
prev_seg->next = seg;
}
- if (seg->type->leftGravity)
+
+ if (seg && seg->type->leftGravity)
{
prev_seg = seg;
}
while (changed)
{
changed = FALSE;
- for (prev_p = &line->segments, seg = *prev_p;
- seg != NULL;
- prev_p = &(*prev_p)->next, seg = *prev_p)
+ prev_p = &line->segments;
+ for (seg = *prev_p; seg != NULL; seg = *prev_p)
{
if (seg->type->cleanupFunc != NULL)
{
*prev_p = (*seg->type->cleanupFunc)(seg, line);
if (seg != *prev_p)
- changed = TRUE;
+ {
+ changed = TRUE;
+ continue;
+ }
}
+
+ prev_p = &(*prev_p)->next;
}
}
}
}
GtkTextLineSegment*
-_gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1,
- const gchar *text2, guint len2)
+_gtk_char_segment_new_from_two_strings (const gchar *text1,
+ guint len1,
+ guint chars1,
+ const gchar *text2,
+ guint len2,
+ guint chars2)
{
GtkTextLineSegment *seg;
memcpy (seg->body.chars + len1, text2, len2);
seg->body.chars[len1+len2] = '\0';
- /* In principle this function could probably take chars1 and chars2
- as args, since it's typically used to merge two char segments */
- seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count);
+ seg->char_count = chars1 + chars2;
if (gtk_debug_flags & GTK_DEBUG_TEXT)
char_segment_self_check (seg);
}
newPtr =
- _gtk_char_segment_new_from_two_strings (segPtr->body.chars, segPtr->byte_count,
- segPtr2->body.chars, segPtr2->byte_count);
+ _gtk_char_segment_new_from_two_strings (segPtr->body.chars,
+ segPtr->byte_count,
+ segPtr->char_count,
+ segPtr2->body.chars,
+ segPtr2->byte_count,
+ segPtr2->char_count);
newPtr->next = segPtr2->next;
guint len);
GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar *text1,
guint len1,
+ guint chars1,
const gchar *text2,
- guint len2);
+ guint len2,
+ guint chars2);
GtkTextLineSegment *_gtk_toggle_segment_new (GtkTextTagInfo *info,
gboolean on);